﻿#region 导入名称空间

using System;
using System.IO;
using System.Linq;
using System.Text;
using SysCrypto = System.Security.Cryptography;

#endregion

namespace LightWork.Cryptography
{
    /// <summary>
    /// 加密帮助类
    /// </summary>
    public static class CryptoUtility
    {
        /// <summary>
        /// 获取SaltSize
        /// </summary>
        /// <param name="password">密码</param>
        /// <param name="iterations">迭代次数</param>
        /// <remarks>注意迭代次数必须大于或等于1000</remarks>
        /// <returns></returns>
        internal static int GetSaltSize(byte[] password, int iterations)
        {
            var salt = SysCrypto.MD5.Create().ComputeHash(password);
            var deriveBytes = new SysCrypto.Rfc2898DeriveBytes(password, salt, iterations);
            var bytes = deriveBytes.GetBytes(2);
            var builder = new StringBuilder();
            for (var i = 0; i < bytes.Length; i++)
                builder.Append(i);
            var strVal = builder.ToString();

            return strVal.Select(charVal => (int) charVal).Aggregate(0, (current, intc) => current + intc);
        }

        /// <summary>
        /// 获取指定位数随机数
        /// </summary>
        /// <param name="length">随机数长度</param>
        /// <returns></returns>
        internal static byte[] GetRandomBytes(int length)
        {
            var randomBytes = new byte[length];
            SysCrypto.RandomNumberGenerator.Create().GetBytes(randomBytes);


            return randomBytes;
        }

        public static SysCrypto.HashAlgorithm GetHashAlgorithm(HashAlgorithmEnum hashAlgorithmEnum)
        {
            switch (hashAlgorithmEnum)
            {
                case HashAlgorithmEnum.SHA1:
                    return new SysCrypto.SHA1CryptoServiceProvider();
                case HashAlgorithmEnum.SHA256:
                    return new SysCrypto.SHA256CryptoServiceProvider();
                case HashAlgorithmEnum.SHA384:
                    return new SysCrypto.SHA384CryptoServiceProvider();
                case HashAlgorithmEnum.SHA512:
                    return new SysCrypto.SHA512CryptoServiceProvider();
                default:
                    return new SysCrypto.MD5CryptoServiceProvider();
            }
        }


        internal static string GetHashed(byte[] input, HashAlgorithmEnum algorithm)
        {
            using (var hashAlgorithm = GetHashAlgorithm(algorithm))
            {
                var hashedArray = hashAlgorithm.ComputeHash(input);

                var hashedStr = BitConverter.ToString(hashedArray).Replace("-", "");
                return hashedStr;
            }
        }

        internal static string GetHashed(Stream input, HashAlgorithmEnum algorithm)
        {
            using (var hashAlgorithm = GetHashAlgorithm(algorithm))
            {
                var hashedArray = hashAlgorithm.ComputeHash(input);

                var hashedStr = BitConverter.ToString(hashedArray).Replace("-", "");
                return hashedStr;
            }
        }


        /// <summary>
        /// 获取哈希值
        /// </summary>
        /// <param name="input">输入</param>
        /// <param name="algorithm">哈希算法</param>
        /// <param name="encoding">字符编码</param>
        /// <returns></returns>
        public static string GetHashed(string input, HashAlgorithmEnum algorithm, Encoding encoding)
        {
            using (var hashAlgorithm = GetHashAlgorithm(algorithm))
            {
                var hashedArray = hashAlgorithm.ComputeHash(encoding.GetBytes(input));

                var hashedStr = BitConverter.ToString(hashedArray).Replace("-", "");
                return hashedStr;
            }
        }

        /// <summary>
        /// 获取哈希值
        /// </summary>
        /// <param name="input">输入</param>
        /// <param name="algorithm">哈希算法</param>
        /// <returns></returns>
        public static string GetHashed(string input, HashAlgorithmEnum algorithm)
        {
            return GetHashed(input, algorithm, Encoding.UTF8);
        }

        /// <summary>
        /// 获取MD5
        /// </summary>
        /// <param name="input">输入</param>
        /// <returns></returns>
        public static string GetMd5(string input)
        {
            return GetHashed(input, HashAlgorithmEnum.MD5, Encoding.UTF8);
        }
        
                /// <summary>
        /// 转换字符串为Byte数组
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private byte[] ToBytes(string input)
        {
            return DefaultEncoding.GetBytes(input);
        }

        /// <summary>
        /// 转Byte数组为换字符串
        /// </summary>
        /// <param name="byteArray"></param>
        /// <returns></returns>
        public string FromBytes(byte[] byteArray)
        {
            return DefaultEncoding.GetString(byteArray);
        }

        /// <summary>
        /// 16进制字符串还原
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        public byte[] FromHex(string hexString)
        {
            hexString = hexString.Replace("-", "");
            var raw = new byte[hexString.Length / 2];
            for (var i = 0; i < raw.Length; i++)
                raw[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);

            return raw;
        }
    }
}